"""
原因：锐捷客户端有时会突然没网，或者机器ip变更，为了防止我的服务器失联所以创建这个脚本

流程：
先检测网络是否畅通，
----畅通则检查ip是否改变，            （1）
--------若改变则法邮件通知我
--------未改变则什么也不用做
----不畅通的话尝试登陆锐捷客户端
--------再次检查网络是否畅通，
------------同（1）
------------不通则重启机器
"""
import re
from email.mime.text import MIMEText
from email.header import Header
import smtplib
import time
import os
import subprocess

FILE_PATH = '/root/tell_ip/'


def run_command(command):
    """
    执行Linux命令，相当于在Linux的shell中运行一样
    :param command:要运行的命令
    :return: None
    """
    os.system(command)


def get_shell_out(command):
    """
    相当于值Linux的shell中运行命令，且返回命令在shell中运行时打印出来的内容
    :param command: 要执行的命令
    :return: 返回命令在shell中运行时打印出来的内容
    """
    child = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    response = child.communicate()[0]
    return response.decode('utf-8')


def send_mail(subject='IP地址变更', content='主机局域网IP地址变更了', receiver=['1206143866@qq.com'],
              text_or_html='plain',
              from_address='我的qq@qq.com',  # **********************************************此处填上正确的qq邮箱
              password='授权码',  # **********************************************填上对应的授权码
              smtp_server='smtp.qq.com',
              smtp_port=465):
    """
    使用qq邮箱发送邮件
    :param subject: 主题
    :param content: 邮件正文
    :param receiver: 邮件接收人，以list形式组织
    :param text_or_html: 邮件形式text还是HTML
    :param from_address:
    :param password: 授权码
    :param smtp_server: 服务器
    :param smtp_port: 端口号
    :return: None
    """
    msg = MIMEText(content, text_or_html, 'utf-8')
    msg['From'] = Header(from_address)
    msg['Subject'] = subject
    send_email = smtplib.SMTP_SSL(host=smtp_server, port=smtp_port)
    send_email.login(from_address, password)
    send_email.sendmail(from_address, receiver, msg.as_string())
    send_email.quit()  # 关闭连接


def check_the_network():
    """
    检查网络: 以ping 百度地址的结果来判断网络是否畅通
    :return:网络畅通返回True，否则返回False
    """
    result = get_shell_out('ping -c 1 www.baidu.com')
    if result.endswith('ms\n'):
        return True
    return False


def get_ip():
    """
    获取有线局域网IP地址并返回
    :return: 能匹配到就返回ip，否则返回None
    """
    pattern = '(10\.16\d\.\d+\.\d+)/21'
    ipa_result = get_shell_out('ip a')
    find_result = re.compile(pattern).search(ipa_result)
    try:
        ip = find_result.group(1)
    except AttributeError:
        ip = None
    finally:
        return ip


def write_some(content, file=FILE_PATH + 'ip.txt'):
    """
    将内容content写入到文件file中，文件存在则覆盖，不存在则新建
    :param content: 要写入的内容
    :param file: 保存的文件
    :return: None
    """
    with open(file, 'w', encoding='utf-8')as f:
        f.write(str(content))


def tell_meip():
    """
    这里封装了一些要多次执行的代码，
    先读取原ip文件中原来的ip地址，让其与当前使用的ip比较，如果不同则更新保存，且发送有奖通知我
    :return: None
    """
    with open(FILE_PATH + 'ip.txt', 'r', encoding='utf-8') as f:
        old_ip = f.read().strip()
    ip = get_ip()  # 因为有网，所以我认为ip肯定不会为None，就不再判断是佛为None了
    if ip != old_ip:
        print_log('主机IP地址变更了' + '新IP为：' + ip)
        try:
            send_mail(subject='右边主机IP地址变更了', content='新IP为：' + ip)  # 处理邮件异常
        except Exception as e:
            print_log('发送邮件时出现异常：' + str(e))
        else:
            write_some(ip)
            print_log('邮件发送完成')


def main():
    """
    整合代码的一个封装函数，即只需运行着一个函数。
    :return:None
    """
    if check_the_network():
        tell_meip()
    else:
        run_command('/root/rjtest/rjsupplicant/rjsupplicant.sh -q')  # 进行一下退出操作
        run_command('/root/tell_ip/net.sh')  # 一个启动锐捷客户端的脚本
        print_log('尝试登录锐捷客户端操作完成')
        time.sleep(10)
        if check_the_network():
            tell_meip()
        else:
            print_log('已经尝试登陆一次客户端了，依旧没网，开始重启电脑')
            run_command('reboot')  # 再次检查是否有网，没有就重启电脑了


def print_log(msg, log_name='ip.log'):
    """
    主要是用来记录一些东西，并且为他们加上时间
    :param msg:
    :param log_name:
    :return:
    """
    with open(FILE_PATH + log_name, 'a', encoding='utf8')as f:
        f.write(time.strftime("[%Y-%m-%d %H:%M:%S] ") + msg + '\n')


if __name__ == '__main__':
    main()
